﻿using System;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;

namespace Tibco.ServiceModel
{
    internal abstract class TibcoChannelListenerBase<TChannel> : ChannelListenerBase<TChannel>
    where TChannel : class, IChannel
    {
        private readonly Func<TimeSpan, TChannel> _acceptChannelMethod;

        private readonly Action<TimeSpan> _closeMethod;

        private readonly BindingContext _context;

        private readonly System.Uri _listenUri;

        private readonly Action<TimeSpan> _openMethod;

        private readonly Func<TimeSpan, bool> _waitForChannelMethod;

        protected TibcoTransportBindingElement m_bindingElement;

        protected BindingContext Context
        {
            get
            {
                return this._context;
            }
        }

        public override System.Uri Uri
        {
            get
            {
                return this._listenUri;
            }
        }

        protected TibcoChannelListenerBase(BindingContext context)
        {
            this._context = context;
            this.m_bindingElement = context.Binding.Elements.Find<TibcoTransportBindingElement>();
            TibcoChannelListenerBase<TChannel> TibcoChannelListenerBase = this;
            this._closeMethod = new Action<TimeSpan>(TibcoChannelListenerBase.OnClose);
            TibcoChannelListenerBase<TChannel> TibcoChannelListenerBase1 = this;
            this._openMethod = new Action<TimeSpan>(TibcoChannelListenerBase1.OnOpen);
            TibcoChannelListenerBase<TChannel> TibcoChannelListenerBase2 = this;
            this._waitForChannelMethod = new Func<TimeSpan, bool>(TibcoChannelListenerBase2.OnWaitForChannel);
            TibcoChannelListenerBase<TChannel> TibcoChannelListenerBase3 = this;
            this._acceptChannelMethod = new Func<TimeSpan, TChannel>(TibcoChannelListenerBase3.OnAcceptChannel);
            if (context.ListenUriMode == ListenUriMode.Explicit && context.ListenUriBaseAddress != null)
            {
                this._listenUri = new System.Uri(context.ListenUriBaseAddress, context.ListenUriRelativeAddress);
                return;
            }

            var uri = new Uri("soap.tibco:///");
            Guid guid = Guid.NewGuid();
            this._listenUri = new Uri(uri, guid.ToString().Replace("-",""));
        }

        protected override void OnAbort()
        {
            this.OnClose(this._context.Binding.CloseTimeout);
        }

        protected override IAsyncResult OnBeginAcceptChannel(TimeSpan timeout, AsyncCallback callback, object state)
        {
            return this._acceptChannelMethod.BeginInvoke(timeout, callback, state);
        }

        protected override IAsyncResult OnBeginClose(TimeSpan timeout, AsyncCallback callback, object state)
        {
            return this._closeMethod.BeginInvoke(timeout, callback, state);
        }

        protected override IAsyncResult OnBeginOpen(TimeSpan timeout, AsyncCallback callback, object state)
        {
            return this._openMethod.BeginInvoke(timeout, callback, state);
        }

        protected override IAsyncResult OnBeginWaitForChannel(TimeSpan timeout, AsyncCallback callback, object state)
        {
            return this._waitForChannelMethod.BeginInvoke(timeout, callback, state);
        }

        protected override TChannel OnEndAcceptChannel(IAsyncResult result)
        {
            return this._acceptChannelMethod.EndInvoke(result);
        }

        protected override void OnEndClose(IAsyncResult result)
        {
            this._closeMethod.EndInvoke(result);
        }

        protected override void OnEndOpen(IAsyncResult result)
        {
            this._openMethod.EndInvoke(result);
        }

        protected override bool OnEndWaitForChannel(IAsyncResult result)
        {
            return this._waitForChannelMethod.EndInvoke(result);
        }
    }
}